package org.lee.whitelist;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.lee.common.domain.Result;
import org.lee.common.util.JsonUtil;
import org.lee.whitelist.annotation.DoFilter;
import org.lee.whitelist.config.StarterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * DoJoinPoint
 *
 * @author dralee
 * @date 2021-11-22 17:11:27
 **/
@Aspect
@Component
@Slf4j
public class DoJoinPoint {

    @Autowired
    private StarterService starterService;

    @Pointcut("@annotation(org.lee.whitelist.annotation.DoFilter)")
    public void aopPoint() {

    }

    @Around("aopPoint()")
    public Object intercept(ProceedingJoinPoint jp) throws Throwable {
        Method method = getMethod(jp);
        DoFilter doFilter = method.getAnnotation(DoFilter.class);
        String key = getFieldValue(doFilter.key(), jp.getArgs());
        log.info("do filter handler method: {} value: {}", method.getName(), key);
        if (null == key || "".equals(key)) {
            return jp.proceed();
        }
        for (String item : starterService.getUserWhiteList()) {
            if (key.equals(item)) {
                return jp.proceed();
            }
        }
        // 拦截
        return returnObject(doFilter, method);
    }

    private Object returnObject(DoFilter doFilter, Method method) throws InstantiationException, IllegalAccessException {
        Class<?> returnType = method.getReturnType();
        String json = doFilter.returnJson();
        if ("".equals(json)) {
            return returnType.newInstance();
        }
        return JsonUtil.fromJson(json, Result.class);
    }

    private String getFieldValue(String fieldName, Object[] args) {
        String value = null;
        for (Object arg : args) {
            try {
                if (null == value || "".equals(value)) {
                    value = BeanUtils.getProperty(arg, fieldName);
                } else {
                    break;
                }
            } catch (Exception e) {
                if (args.length == 1) {
                    return args[0].toString();
                }
            }
        }
        return value;
    }

    private Method getMethod(ProceedingJoinPoint jp) throws NoSuchMethodException {
        MethodSignature signature = (MethodSignature) jp.getSignature();
        return getClass(jp).getMethod(signature.getName(), signature.getParameterTypes());
    }

    private Class<? extends Object> getClass(JoinPoint jp) {
        return jp.getTarget().getClass();
    }
}
